package com.molichuxing.gateway.bff.car.services.impl;

import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.RedisUtil;
import com.molichuxing.gateway.bff.car.entity.response.*;
import com.molichuxing.gateway.bff.car.services.ViolationBffService;
import com.molichuxing.gateway.utils.RequestAttrUtil;
import com.molichuxing.services.business.dto.response.CarDetailBizDto;
import com.molichuxing.services.business.dto.response.OrderCarInfoAppDto;
import com.molichuxing.services.business.dto.response.ViolationBeanDto;
import com.molichuxing.services.business.service.CarBizService;
import com.molichuxing.services.business.service.ClxBizService;
import com.molichuxing.services.business.service.OrderBizService;
import com.molichuxing.services.infrastructure.dto.request.create.ViolationCreateDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.CarViolationEnum;
import com.molichuxing.services.property.CarViolationOpTypeEnum;
import com.molichuxing.services.property.OrderExclusivelStatusEnum;
import com.molichuxing.services.property.OrderSubscribeStatusEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: renzhengyu
 * @Description:
 * @Date: Created in 15:24 2019/9/23
 * @Modified By:
 **/
@Service("violationBffService")
public class ViolationBffServiceImpl implements ViolationBffService {
    private static final Logger logger = LoggerFactory.getLogger(ViolationBffServiceImpl.class);

    @Resource
    private CarService carService;

    @Resource
    private VehicleService vehicleService;

    @Resource
    private VehicleModleService vehicleModleService;

    @Resource
    private OrderReturnService orderReturnService;

    @Resource
    private OrderDeliveryService orderDeliveryService;

    @Resource
    private ClxBizService clxBizService;

    @Resource
    private CarBizService carBizService;

    @Resource
    private CarViolationService carViolationService;

    @Resource
    private OrderBizService orderBizService;

    @Resource
    private StoreService storeService;

    @Resource
    private RedisUtil redisUtil;

    @Value("${violation.time}")
    private Integer violationTime;

    public final static String VIOLATION_KEY = "violation:";

    private static final Integer VIOLATION_CODE = 1008;

    private static final Integer NO_VIOLATION_CODE = 1009;

    /**
     * 违章列表
     * @return
     * @throws Exception
     */
    @Override
    public List<CarViolationVo> getCarViolationAppVo() throws Exception {
        List<CarViolationVo> carViolationVoList = null;
        //获取当前登录的用户id
        Integer userId = RequestAttrUtil.getCurrentUserId();
        if(null == userId){
            throw new Exception("用户未登录");
        }
        List<OrderCarInfoAppDto> orderCarInfoAppDtoList = orderBizService.getCarIdsByUser(userId,0);
        if(null == orderCarInfoAppDtoList || orderCarInfoAppDtoList.size()<= 0){
            return carViolationVoList;
        }
        carViolationVoList = new ArrayList<>();

        String key = getKey(userId);
        String check = redisUtil.get(key);
        if(null != check){
               //不是当天第一次查询
                //返回列表
                List<CarViolationAppDto> carViolationAppDtoList = carViolationService.getCarViolationAppDtoByUserId(userId);
                if(null == carViolationAppDtoList || carViolationAppDtoList.size() <= 0){
                    return carViolationVoList;
                }
                CarViolationVo carViolationVo = null;
                for (CarViolationAppDto carViolationAppDto:carViolationAppDtoList) {
                    carViolationVo = new CarViolationVo();
                    BeanUtils.copyProperties(carViolationAppDto, carViolationVo);
                    //获取车辆基础信息
                    CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carViolationAppDto.getCarId());
                    if(null == carDetailBizDto){
                        throw new Exception("非法入参");
                    }
                    VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDetailBizDto.getVehicleId());
                    if(null == vehicleDto){
                        throw new Exception("非法入参");
                    }
                    VehicleModleDto vehicleModleDto = vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId());
                    if(null == vehicleModleDto){
                        throw new Exception("非法入参");
                    }
                    carViolationVo.setModelImg(vehicleModleDto.getWhiteFigure());
                    carViolationVoList.add(carViolationVo);
                }

                return carViolationVoList;
        }else{
            //当天第一次查询
            //用户所有车辆
            for (OrderCarInfoAppDto orderCarInfoAppDto:orderCarInfoAppDtoList) {
                if(null == orderCarInfoAppDto.getCarId() || null == orderCarInfoAppDto.getOrderStatus() || OrderSubscribeStatusEnum.TRADE_CANCELED.getValue() == orderCarInfoAppDto.getOrderStatus()){
                    continue;
                }
                CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(orderCarInfoAppDto.getCarId());
                if(null == carDetailBizDto){
                    throw new Exception("非法入参");
                }
                VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDetailBizDto.getVehicleId());
                if(null == vehicleDto){
                    throw new Exception("非法入参");
                }
                VehicleModleDto vehicleModleDto = vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId());
                if(null == vehicleModleDto){
                    throw new Exception("非法入参");
                }
                //查询该车辆的提车时间
                OrderDeliveryDto orderDeliveryDto = orderDeliveryService.getOrderDelivery(orderCarInfoAppDto.getOrderCode());
                if(null == orderDeliveryDto){
                    continue;
                }
                //查询车辆是否违章
                ResponseResult<List<ViolationBeanDto>> result = clxBizService.getClxViolation(carDetailBizDto.getLicencePlate(),carDetailBizDto.getVin(),carDetailBizDto.getEngineCode());

                //状态码为1008表示有违章
                if(VIOLATION_CODE.equals(result.getCode())){
                    //查询该车辆的还车时间
                    OrderReturnDto orderReturnDto = orderReturnService.getOrderReturn(orderCarInfoAppDto.getOrderCode());
                    if(null == orderReturnDto){
                        //未还车
                        for (ViolationBeanDto violationBeanDto:result.getData()) {
                            // 取该车辆提车-当前时间区间的违章数据
                            if(violationBeanDto.getRegulationTime().isAfter(orderDeliveryDto.getDeliveryTime())  && violationBeanDto.getRegulationTime().isBefore(LocalDateTime.now())){

                                //根据用户id，车辆id，违章时间查询库中是否有数据
                                CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(userId,orderCarInfoAppDto.getCarId(),violationBeanDto.getRegulationTime());
                                if(null == carsViolationDto){
                                    //如果没数据，则新建违章表
                                    createViolation(orderCarInfoAppDto,violationBeanDto,carDetailBizDto,userId);
                                }else{
                                	//如果有数据，判断当前违章状态是否与库中一致，不一致则更新数据库
                                	Integer status = Integer.valueOf(carsViolationDto.getStatus());
                                	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
                                	//如果   标记已缴费  则不去处理该数据
                                	if(!CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
                                		if(!status.equals(violationBeanDto.getStatus())){
                                            updateViolationById(carsViolationDto,violationBeanDto);
                                        }
                                	}
                                }
                            }
                        }
                    }else{
                        //已还车
                        for (ViolationBeanDto violationBeanDto:result.getData()) {
                            // 取该车辆提车-还车区间的违章数据
                            if(violationBeanDto.getRegulationTime().isAfter(orderDeliveryDto.getDeliveryTime())  && violationBeanDto.getRegulationTime().isBefore(orderReturnDto.getReturnTime())){
                                //根据用户id，车辆id，违章时间查询库中是否有数据
                                CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(userId,orderCarInfoAppDto.getCarId(),violationBeanDto.getRegulationTime());
                                if(null == carsViolationDto){
                                    //如果没数据，则新建违章表
                                    createViolation(orderCarInfoAppDto,violationBeanDto,carDetailBizDto,userId);
                                }else{
                                	//如果有数据，判断当前违章状态是否与库中一致，不一致则更新数据库
                                	Integer status = Integer.valueOf(carsViolationDto.getStatus());
                                	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
                                	//如果   标记已缴费  则不去处理该数据
                                	if(!CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
                                		if(!status.equals(violationBeanDto.getStatus())){
                                            updateViolationById(carsViolationDto,violationBeanDto);
                                        }
                                	}
                                }
                            }
                        }
                    }
                }else if(NO_VIOLATION_CODE.equals(result.getCode())){
                    //如果无违章  则验证本地库是否存在违章 ，如果存在则修改状态（改为违章已处理）
                    carViolationService.modifyViolationStatusByCarId(orderCarInfoAppDto.getCarId());
                }
            }
            //创建每日第一次查询key
            redisUtil.setex(key, "",Integer.valueOf(violationTime));
        }
        //返回列表
        List<CarViolationAppDto> carViolationAppDtoList = carViolationService.getCarViolationAppDtoByUserId(userId);
        if(null == carViolationAppDtoList || carViolationAppDtoList.size() <= 0){
            return carViolationVoList;
        }
        CarViolationVo carViolationVo = null;
        for (CarViolationAppDto carViolationAppDto:carViolationAppDtoList) {
            carViolationVo = new CarViolationVo();
            BeanUtils.copyProperties(carViolationAppDto, carViolationVo);
            //获取车辆基础信息
            CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carViolationAppDto.getCarId());
            if(null == carDetailBizDto){
                throw new Exception("非法入参");
            }
            VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDetailBizDto.getVehicleId());
            if(null == vehicleDto){
                throw new Exception("非法入参");
            }
            VehicleModleDto vehicleModleDto = vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId());
            if(null == vehicleModleDto){
                throw new Exception("非法入参");
            }
            carViolationVo.setModelImg(vehicleModleDto.getWhiteFigure());
            carViolationVoList.add(carViolationVo);
        }

        return carViolationVoList;
    }

    /**
     * 违章详情
     * @param carId
     * @return
     * @throws Exception
     */
    @Override
    public CarViolationDetailAppVo getCarViolationDetailAppVo(Integer carId) throws Exception {
        //获取当前登录的用户id
        Integer userId = RequestAttrUtil.getCurrentUserId();
        if(null == userId){
            throw new Exception("用户未登录");
        }
        return getCarViolationDetailAppVo(carId,userId);
    }


    /**
     * 查询用户拥有车辆数
     * @return
     */
    @Override
    public List<Integer> getCarViolationCarCount() throws Exception {
        //获取当前登录的用户id
        Integer userId = RequestAttrUtil.getCurrentUserId();
        if(null == userId){
            throw new Exception("用户未登录");
        }
        List<Integer> carIdList = new ArrayList<>();
        List<OrderCarInfoAppDto> orderCarInfoAppDtoList = orderBizService.getCarIdsByUser(userId,0);
        if(null == orderCarInfoAppDtoList  || orderCarInfoAppDtoList.size()<= 0){
            return carIdList;
        }

        for (OrderCarInfoAppDto orderCarInfoAppDto:orderCarInfoAppDtoList) {
            List<CarsViolationDto> carsViolationDtoList = carViolationService.getCarsViolationByUserId(userId,orderCarInfoAppDto.getCarId());
            if(null == carsViolationDtoList || carsViolationDtoList.size() <= 0){
                continue;
            }
            carIdList.add(orderCarInfoAppDto.getCarId());
        }
        return carIdList;
    }


    private CarViolationDetailAppVo getCarViolationDetailAppVo(Integer carId ,Integer userId) throws Exception {
        CarViolationDetailAppVo carViolationDetailAppVo = null;
        //获取车辆基础信息
        CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carId);
        if(null == carDetailBizDto){
            throw new Exception("非法入参");
        }
        VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDetailBizDto.getVehicleId());
        if(null == vehicleDto){
            throw new Exception("非法入参");
        }
        VehicleModleDto vehicleModleDto = vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId());
        if(null == vehicleModleDto){
            throw new Exception("非法入参");
        }
        List<CarsViolationDto> carsViolationDtoList = carViolationService.getCarsViolationByUserId(userId,carId);
        if(null == carsViolationDtoList || carsViolationDtoList.size() <= 0){
            return carViolationDetailAppVo;
        }

        carViolationDetailAppVo = new CarViolationDetailAppVo();

        CarViolationCarInfoVo carViolationCarInfoVo = new CarViolationCarInfoVo();
        carViolationCarInfoVo.setCarId(carDetailBizDto.getCarId());
        carViolationCarInfoVo.setLicencePlate(carDetailBizDto.getLicencePlate());
        carViolationCarInfoVo.setVehicleStyleStr(vehicleDto.getName());
        carViolationCarInfoVo.setModelImg(vehicleModleDto.getWhiteFigure());

        carViolationDetailAppVo.setCarViolationCarInfoVo(carViolationCarInfoVo);

        List<CarViolationDetailVo> carViolationDetailVoList = new ArrayList<>();
        CarViolationDetailVo carViolationDetailVo = null;
        for (CarsViolationDto carsViolationDto:carsViolationDtoList) {
            carViolationDetailVo = new CarViolationDetailVo();
            BeanUtils.copyProperties(carsViolationDto, carViolationDetailVo);
            carViolationDetailVo.setStatusStr(CarViolationEnum.getName(Integer.valueOf(carsViolationDto.getStatus())));
            carViolationDetailVoList.add(carViolationDetailVo);
        }
        carViolationDetailAppVo.setCarViolationDetailVoList(carViolationDetailVoList);
        return carViolationDetailAppVo;
    }

    /**
     * 更新违章
     * @param carsViolationDto
     * @return
     */
    private void updateViolationById(CarsViolationDto carsViolationDto,ViolationBeanDto violationBeanDto) throws Exception {
        //不一致则更新数据库
        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
        violationCreateDto.setId(carsViolationDto.getId());
        violationCreateDto.setStatus((byte)violationBeanDto.getStatus().intValue());
        if(null != violationBeanDto.getHandlingTime() ){
            violationCreateDto.setHandlingTime(violationBeanDto.getHandlingTime());
        }
        violationCreateDto.setGmtModified(LocalDateTime.now());
        int ret = carViolationService.updateById(violationCreateDto);
        if(ret < 0){
            logger.error("更新违章信息失败,CarId:"+carsViolationDto.getCarId());
            throw new Exception("更新违章信息失败");
        }
    }

    /**
     * 创建违章
     * @param orderCarInfoAppDto
     * @param violationBeanDto
     * @param carDetailBizDto
     * @param userId
     * @return
     * @throws Exception
     */
    private void createViolation(OrderCarInfoAppDto orderCarInfoAppDto,ViolationBeanDto violationBeanDto,CarDetailBizDto carDetailBizDto,Integer userId) throws Exception {
        //根据门店id查询经销商信息
        StoreDto storeDto = storeService.getStoreById(orderCarInfoAppDto.getPlaceStoreId());
        if(null == storeDto){
            throw new Exception("非法入参");
        }
        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
        BeanUtils.copyProperties(violationBeanDto,violationCreateDto);
        violationCreateDto.setCarId(carDetailBizDto.getCarId());
        violationCreateDto.setOrderCode(orderCarInfoAppDto.getOrderCode());
        violationCreateDto.setDealerId(storeDto.getDealerId());
        violationCreateDto.setUserId(userId);
        violationCreateDto.setVin(carDetailBizDto.getVin());
        violationCreateDto.setFineFee(new BigDecimal(violationBeanDto.getFineFee()));
        violationCreateDto.setStatus(violationBeanDto.getStatus().byteValue());
        violationCreateDto.setEngineCode(carDetailBizDto.getEngineCode());
        int ret = carViolationService.createViolation(violationCreateDto);
        if(ret < 0){
            logger.error("新建违章信息失败,CarId:"+carDetailBizDto.getCarId());
            throw new Exception("新建违章信息失败");
        }
    }

    private static String getKey(Integer userId) {
        if(null == userId){
            return null;
        }
        return VIOLATION_KEY.concat(DateUtil.formatLocalDateNow().concat(String.valueOf(userId)));
    }
}
